<script setup lang="ts">
import { computed, ref, unref, useAttrs } from "vue";
import { tableProps } from ".";
import { ElTable, TableInstance } from "element-plus";
import { usePagination } from "./hooks/usePagination";
import { BasicTableProps, TableActionType } from "./types";
import useDataSource from "./hooks/useDataSource";
import TableCell from "./components/TableCell.vue";
import { useColumns } from "./hooks/useColumns";
import { useSearchForm } from "./hooks/useSearchForm";
import TableSearchForm from "./components/TableSearchForm.vue";
import { useRowSelection } from "./hooks/useRowSelection";

// defineOptions({ name: 'BasicTable' })

const props = defineProps({
  ...tableProps,
});

const emit = defineEmits(["register", "fetch-success", "fetch-error", "rowClick"]);

// extend prefix
const prefixCls = "F-table";
// setup context
const attrs = useAttrs();
// const emits = ref({});

const tableElRef = ref<TableInstance>();
const tableData = ref([]);

const innerPropsRef = ref<Partial<BasicTableProps>>();

// 获取属性
const getProps = computed<BasicTableProps>(() => {
  return {
    ...props,
    ...unref(innerPropsRef),
  };
});

function setProps(props: Partial<BasicTableProps>) {
  innerPropsRef.value = { ...unref(innerPropsRef), ...props };
}

// use pagination
const {
  showPagination,
  currentPage,
  pageSize,
  getPaginationProps,
  getMetaInfo,
  setTotal,
  setCurrentPage,
} = usePagination(getProps);

// use search form
const {
  showSearchFrom,
  getSearchParams,
  getShowSearchButton,
  formItems,
  formData,
  getSearchInfo,
  reset,
  setFormItems,
  setFormData,
} = useSearchForm(getProps);

// use table data
const { loading, fetch, getDataRef, getRowKey, reload, getData, setSortInfo } =
  useDataSource(
    getProps,
    {
      getMetaInfo,
      getSearchParams,
      tableData,
      setTotal,
      setCurrentPage,
      clearSelectedRowKeys: () => {},
    },
    emit
  );

  const handleRowClick = (row: any, event: MouseEvent) => {
      // 双击事件
      emit('rowClick', row);
  };

// use columns
const { fields, getCheckedColumns, getColumnsByFields, getShowButton } =
  useColumns(getProps);

const {
  clearSelection,
  toggleRowSelection,
  toggleAllSelection,
  getSelectionRows,
} = useRowSelection(tableElRef);

/**
 * 绑定属性
 */
const getBindValues = computed(() => {
  const data = unref(getDataRef);
  return {
    stripe: true,
    ...attrs,
    ...unref(getProps),
    rowKey: unref(getRowKey),
    data,
  };
});

const expandRowKeys = ref<string[]>();
const setExpandRowKeys = (rowKeys: string[]) => {
  expandRowKeys.value = rowKeys;
};

const tableAction: TableActionType = {
  setProps,
  reload,
  getData,
  clearSelection,
  toggleRowSelection,
  toggleAllSelection,
  getSelectionRows,
  setExpandRowKeys,
  getSearchInfo,
  setFormItems,
  setFormData,
};

emit("register", tableAction);

defineExpose({ tableAction });
</script>

<template>
  <div :class="prefixCls">
    <!-- 搜索选项 -->
    <TableSearchForm
      v-if="showSearchFrom"
      v-model="formData"
      :form-items="formItems"
      @search="reload"
      @reset="
        () => {
          reset();
          reload();
        }
      ">
    </TableSearchForm>
    <!-- 操作选项 -->
    <el-row
      v-if="!getProps.hideTableHeader"
      :class="prefixCls + '-header'">
      <el-col
        :class="prefixCls + '-header-left'"
        :span="12">
        <slot name="header-left"></slot>
      </el-col>
      <el-col
        :class="prefixCls + '-header-right'"
        :span="12">
        <el-tooltip content="刷新">
          <el-button @click="reload"
            ><el-icon><RefreshRight /></el-icon
          ></el-button>
        </el-tooltip>
        <el-tooltip
          v-if="getShowSearchButton"
          :content="showSearchFrom ? '隐藏搜索' : '显示搜索'">
          <el-button @click="showSearchFrom = !showSearchFrom"
            ><el-icon><Search /></el-icon
          ></el-button>
        </el-tooltip>
        <el-popover
          v-if="getShowButton"
          placement="bottom-end">
          <template #reference>
            <el-button
              ><el-icon><Menu></Menu></el-icon
            ></el-button>
          </template>
          <el-checkbox-group v-model="fields">
            <el-checkbox
              v-for="(item, index) in getCheckedColumns"
              :key="index"
              :label="item.label"
              :value="item.prop" />
          </el-checkbox-group>
        </el-popover>
      </el-col>
    </el-row>
    <!-- 表头 -->
    <slot name="table-header"></slot>
    <!-- 内容区域 -->
    <div :class="prefixCls + '-content'">
      <slot name="table-tabs"></slot>
      <!-- 表格 -->
      <el-table
        ref="tableElRef"
        :expand-row-keys="expandRowKeys"
        v-bind="getBindValues"
        v-loading="loading"
        @sort-change="setSortInfo"
        @row-click="handleRowClick">
        <!-- 其他列表 -->
        <el-table-column
          v-for="(column, index) in getColumnsByFields"
          :key="index"
          minWidth="120"
          showOverflowTooltip
          v-bind="column">
          <!-- 表头插槽 -->
          <template
            v-if="$slots[`${column.prop}:header`]"
            #header="scope">
            <slot
              :name="`${column.prop}:header`"
              v-bind="scope"></slot>
          </template>
          <!-- 内容插槽 -->
          <template #default="scope">
            <!-- 固定插槽 -->
            <slot
              v-if="column.type !== 'default' && $slots[column.prop!]"
              :name="column.prop"
              v-bind="scope"></slot>
            <slot
              v-else-if="column.type === undefined || column.type === 'default'"
              :name="column.prop"
              v-bind="scope">
              <!-- 自定义内容或组件 -->
              <TableCell
                :column="column"
                :value="scope.row"
                :index="scope.$index" />
            </slot>
          </template>
        </el-table-column>
        <!-- table 插槽映射 -->
        <template
          #[item]="data"
          v-for="item in Object.keys($slots)"
          :key="item">
          <slot
            :name="item"
            v-bind="data || {}"></slot>
        </template>
      </el-table>
      <!-- 分页 -->
      <el-row
        v-if="showPagination"
        :class="prefixCls + '-footer'">
        <el-pagination
          v-model:current-page="currentPage"
          v-model:page-size="pageSize"
          v-bind="getPaginationProps"
          @change="fetch" />
      </el-row>
    </div>
  </div>
</template>

<style scoped lang="scss">
$prefix: "F-table";

.#{$prefix} {
  max-width: 100%;
  height: 100%;
}
.#{$prefix}-header {
  margin-bottom: 10px;
}
.#{$prefix}-header-right {
  text-align: right;
}

.#{$prefix}-content {
  padding: 10px;
  border-radius: 4px;
  background-color: var(--el-bg-color);
}
.#{$prefix}-footer {
  justify-content: flex-end;
  margin-top: 10px;
}
</style>
